package controls

import (
	"github.com/dgrijalva/jwt-go"
	"github.com/labstack/echo/v4"
	"github.com/rs/xid"
	"os"
	"regexp"
	"sofuny/models"
	"sofuny/utils"
	"strings"
	"time"
)

// sentences
func AdminFindAllSentence(ctx echo.Context) error {
	var sentences []models.Sentence
	if err := db.Order("create_at desc").Find(&sentences).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "获取句子失败",
			Data:  err.Error(),
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	return ctx.JSON(200, utils.Response{
		Code:  200,
		Msg:   "success",
		Data:  sentences,
		Total: len(sentences),
		Time:  utils.FormatTime(),
	})
}

// 添加
func AdminAddSentence(ctx echo.Context) error {
	var sentence models.Sentence
	var v utils.Value
	// 绑定数据
	if err := ctx.Bind(&v); err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   utils.DataBindErrorMessage,
			Data:  err.Error(),
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 判断数据
	if v.NewSentence == "" || v.Source == "" {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   utils.DataEmptyMessage,
			Data:  nil,
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 赋值
	sentence.CreateAt = time.Now().Local()
	sentence.UpdateAt = sentence.CreateAt
	sentence.Uuid = xid.New().String()
	sentence.Status = true
	sentence.Source = v.Source
	sentence.Content = v.NewSentence

	// 创建
	if err := db.Create(&sentence).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "创建句子失败",
			Data:  err.Error(),
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 创建成功
	return ctx.JSON(200, utils.Response{
		Code:  200,
		Msg:   "创建句子成功",
		Data:  sentence,
		Total: 1,
		Time:  utils.FormatTime(),
	})
}

// 修改
func AdminChangeSentence(ctx echo.Context) error {
	var v utils.Value
	var sentence models.Sentence
	// 数据绑定
	if err := ctx.Bind(&v); err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   utils.DataBindErrorMessage,
			Data:  err.Error(),
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	// 查询文章
	if err := db.Where("uuid=?", v.Uuid).Find(&sentence).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "获取句子失败",
			Data:  err.Error(),
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	// 更新数据
	sentence.UpdateAt = time.Now().Local()
	sentence.Source = v.Source
	sentence.Content = v.Content
	if err := db.Save(&sentence).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "更新句子失败!",
			Data:  err.Error(),
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 返回
	return ctx.JSON(200, utils.Response{
		Code:  200,
		Msg:   "更新成功",
		Data:  sentence,
		Total: 0,
		Time:  utils.FormatTime(),
	})
}

// 删除
func AdminDeleteSentence(ctx echo.Context) error {
	var v utils.Value
	var sentence models.Sentence
	// 数据绑定
	if err := ctx.Bind(&v); err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   utils.DataBindErrorMessage,
			Data:  err.Error(),
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	// 判断数据
	if v.Uuid == "" {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "uuid不允许为空",
			Data:  nil,
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 查找句子
	if err := db.Where("uuid=?", v.Uuid).Find(&sentence).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "获取句子失败",
			Data:  err.Error(),
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	// 执行删除
	if err := db.Unscoped().Delete(&sentence).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "删除句子失败",
			Data:  err.Error(),
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	// 删除成功
	return ctx.JSON(200, utils.Response{
		Code:  200,
		Msg:   "删除成功!",
		Data:  nil,
		Total: 0,
		Time:  utils.FormatTime(),
	})
}

// 订阅
func AdminFindAllSubscribe(ctx echo.Context) error {
	var subscribes []models.Subscribe
	if err := db.Order("create_at desc").Find(&subscribes).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "获取订阅失败",
			Data:  err.Error(),
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	return ctx.JSON(200, utils.Response{
		Code:  200,
		Msg:   "success",
		Data:  subscribes,
		Total: len(subscribes),
		Time:  utils.FormatTime(),
	})
}

// 添加
func AdminAddSubscribe(ctx echo.Context) error {
	var subscribe models.Subscribe
	// 绑定数据
	if err := ctx.Bind(&subscribe); err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   utils.DataBindErrorMessage,
			Data:  err.Error(),
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 判断数据
	if subscribe.Email == "" {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "邮箱不允许为空",
			Data:  nil,
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 赋值
	subscribe.CreateAt = time.Now().Local()
	subscribe.UpdateAt = subscribe.CreateAt
	subscribe.Uuid = xid.New().String()
	subscribe.Status = true
	// 创建
	if err := db.Create(&subscribe).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "创建订阅失败",
			Data:  err.Error(),
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 创建成功
	return ctx.JSON(200, utils.Response{
		Code:  200,
		Msg:   "创建订阅成功",
		Data:  subscribe,
		Total: 1,
		Time:  utils.FormatTime(),
	})
}

//修改
func AdminChangeSubscribe(ctx echo.Context) error {
	var value models.Subscribe
	var subscribe models.Subscribe
	// 数据绑定
	if err := ctx.Bind(&value); err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   utils.DataBindErrorMessage,
			Data:  err.Error(),
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	// 查询文章
	if err := db.Where("uuid=?", value.Uuid).Find(&subscribe).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "获取订阅失败",
			Data:  err.Error(),
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	// 更新数据
	subscribe.UpdateAt = time.Now().Local()
	if err := db.Model(&subscribe).Updates(&value).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "更新订阅失败!",
			Data:  err.Error(),
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	return ctx.JSON(200, utils.Response{
		Code:  200,
		Msg:   "更新成功",
		Data:  nil,
		Total: 0,
		Time:  utils.FormatTime(),
	})
}

// 删除
func AdminDeleteSubscribe(ctx echo.Context) error {
	var v utils.Value
	var subscribe models.Subscribe
	// 数据绑定
	if err := ctx.Bind(&v); err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   utils.DataBindErrorMessage,
			Data:  err.Error(),
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	// 判断数据
	if v.Uuid == "" {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "uuid不允许为空",
			Data:  nil,
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 查找句子
	if err := db.Where("uuid=?", v.Uuid).Find(&subscribe).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "获取订阅失败",
			Data:  err.Error(),
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	// 执行删除
	if err := db.Unscoped().Delete(&subscribe).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "删除订阅失败",
			Data:  err.Error(),
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	// 删除成功
	return ctx.JSON(200, utils.Response{
		Code:  200,
		Msg:   "删除成功!",
		Data:  nil,
		Total: 0,
		Time:  utils.FormatTime(),
	})
}

// 登录
func UserLogin(ctx echo.Context) error {
	var v utils.Value
	var user models.User
	if err := ctx.Bind(&v); err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   utils.DataBindErrorMessage,
			Data:  err.Error(),
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 判断数据
	if v.Username == "" || v.Password == "" {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "数据不允许为空",
			Data:  nil,
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 查找用户
	if err := db.Where("username=? and status=? and is_superuser=?", v.Username, true, true).Find(&user).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "用户不存在!",
			Data:  err.Error(),
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 判断密码
	if utils.MD5(v.Password) != user.Password {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "密码错误",
			Data:  nil,
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 登录成功
	// Create token
	token := jwt.New(jwt.SigningMethodHS256)

	// Set claims
	claims := token.Claims.(jwt.MapClaims)
	claims["id"] = user.ID
	claims["name"] = user.Username
	claims["admin"] = true
	claims["exp"] = time.Now().Add(time.Hour * 72).Unix()

	// Generate encoded token and send it as response.
	t, err := token.SignedString([]byte("secret"))
	if err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "生成jwt错误!",
			Data:  err.Error(),
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	return ctx.JSON(200, utils.Response{
		Code: 200,
		Msg:  "登录成功",
		Data: map[string]string{
			"username": user.Username,
			"avatar":   user.Avatar,
			"token":    t,
		},
		Total: 1,
		Time:  utils.FormatTime(),
	})
}

// 文章 添加
func AdminAddArticle(ctx echo.Context) error {
	var v utils.Value
	var article models.Article
	if err := ctx.Bind(&v); err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   utils.DataBindErrorMessage,
			Data:  err.Error(),
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 判断数据
	if v.Title == "" || v.Author == "" || v.Category == "" || len(v.Tags) == 0 || v.Content == "" || v.ImgUrl == "" {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   utils.DataEmptyMessage,
			Data:  nil,
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 赋值
	article.CreateAt = time.Now().Local()
	article.UpdateAt = article.CreateAt
	article.Uuid = xid.New().String()
	article.Status = true
	article.Title = v.Title
	article.Author = v.Author
	article.Type = v.Type
	article.ImgUrl = v.ImgUrl
	article.Category = v.Category
	article.Tags = strings.Join(v.Tags, ",")
	article.Abstract = v.Abstract
	article.Content = v.Content

	// 创建文章
	if err := db.Create(&article).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  200,
			Msg:   "创建文章失败",
			Data:  err,
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	// 成功
	return ctx.JSON(200, utils.Response{
		Code:  200,
		Msg:   "success",
		Data:  article,
		Total: 1,
		Time:  utils.FormatTime(),
	})
}

// 所有文章
func AdminFindAllArticle(ctx echo.Context) error {
	var articles []models.Article
	if err := db.Order("create_at desc").Find(&articles).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "获取文章失败",
			Data:  err,
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	// 返回数据
	return ctx.JSON(200, utils.Response{
		Code:  200,
		Msg:   "success",
		Data:  articles,
		Total: len(articles),
		Time:  utils.FormatTime(),
	})
}

// 查找文章
func AdminFindArticle(ctx echo.Context) error {
	var article models.Article
	uuid := ctx.QueryParam("uuid")
	// 判断数据
	if uuid == "" {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   utils.DataEmptyMessage,
			Data:  nil,
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	//
	if err := db.Where("status=? and uuid=?", true, uuid).First(&article).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "获取文章失败",
			Data:  err,
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	// 返回数据
	return ctx.JSON(200, utils.Response{
		Code:  200,
		Msg:   "success",
		Data:  article,
		Total: 1,
		Time:  utils.FormatTime(),
	})
}

// 修改文章
func AdminChangeArticle(ctx echo.Context) error {
	var v utils.Value
	var article models.Article
	// 绑定数据
	if err := ctx.Bind(&v); err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   utils.DataBindErrorMessage,
			Data:  err,
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	// 判断 数据
	if v.Title == "" || v.Author == "" || v.Category == "" || len(v.Tags) == 0 || v.Content == "" || v.ImgUrl == "" {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   utils.DataEmptyMessage,
			Data:  nil,
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 查找文章
	if err := db.Where("uuid=?", v.Uuid).First(&article).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "获取文章失败",
			Data:  err,
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	// 判断原数据 与修改数据的 异同
	//必须保证imgUrl 不能为空
	if v.ImgUrl == "" || article.ImgUrl == "" {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "文章配图允许为空",
			Data:  nil,
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 文章配图
	if v.ImgUrl != article.ImgUrl {
		// 删除 原来的 配图
		// 获取要移除的文件名 必须包含要移除图片名
		fileNames := strings.Split(article.ImgUrl, "/")
		// 获取当前路径
		pwdPath, _ := os.Getwd()
		// 执行移除图片
		_ = os.Remove(pwdPath + "/static/image/article/" + fileNames[len(fileNames)-1])
	}
	// TODO 判断文章内容的图片 是否改变

	// 对比 v.Content article.Content

	// 赋值
	article.UpdateAt = time.Now().Local()
	article.Title = v.Title
	article.Author = v.Author
	article.Type = v.Type
	article.ImgUrl = v.ImgUrl
	article.Category = v.Category
	article.Tags = strings.Join(v.Tags, ",")
	article.Abstract = v.Abstract
	article.Content = v.Content

	// 保存修改
	if err := db.Save(&article).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "修改文章失败",
			Data:  err,
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	// 修改成功
	return ctx.JSON(200, utils.Response{
		Code:  200,
		Msg:   "success",
		Data:  article,
		Total: 1,
		Time:  utils.FormatTime(),
	})
}

// 删除文章
func AdminDeleteArticle(ctx echo.Context) error {
	var v utils.Value
	var article models.Article
	// 数据绑定
	if err := ctx.Bind(&v); err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   utils.DataBindErrorMessage,
			Data:  err,
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	// 判断数据
	if v.Uuid == "" {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "uuid不允许为空",
			Data:  nil,
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 查找文章
	if err := db.Where("uuid=?", v.Uuid).Find(&article).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "获取文章失败",
			Data:  err,
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}

	// 获取当前路径
	pwdPath, _ := os.Getwd()

	// 获取文章内容中的图片链接
	// TODO 有点复杂 后期再去优化 正则 或者删除退片的逻辑 放在一个函数里
	var re = regexp.MustCompile(`(?m)/static/image/article/(.*?)\)(?m)`)
	images := re.FindAllString(article.Content, -1)

	if len(images) != 0 {
		for i := 0; i < len(images); i++ {
			imageNames := strings.Split(strings.Replace(images[i], ")", "", -1), "/")
			// 执行移除图片
			_ = os.Remove(pwdPath + "/static/image/article/" + imageNames[len(imageNames)-1])
		}
	}

	// 获取要移除的文件名 必须包含要移除图片名
	if article.ImgUrl == "" {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "文章配图为空，删除失败",
			Data:  nil,
			Total: 0,
			Time:  utils.FormatTime(),
		})
	}
	// 删除文章配图以及文章内的图片
	fileNames := strings.Split(article.ImgUrl, "/")

	// 执行移除图片
	_ = os.Remove(pwdPath + "/static/image/article/" + fileNames[len(fileNames)-1])

	// 执行删除 文章
	if err := db.Unscoped().Delete(&article).Error; err != nil {
		return ctx.JSON(200, utils.Response{
			Code:  201,
			Msg:   "删除文章失败",
			Data:  err,
			Total: 1,
			Time:  utils.FormatTime(),
		})
	}
	// 删除成功
	return ctx.JSON(200, utils.Response{
		Code:  200,
		Msg:   "删除成功!",
		Data:  nil,
		Total: 0,
		Time:  utils.FormatTime(),
	})
}
